﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

public class SceneAssetBundle
{ 
    //包名 和 对应包的映射
    private Dictionary<string, AssetBundleRelation> relationList = null;
    //包名 和对应包的缓存
    private Dictionary<string, AssetCaching> nameCacheDic = null;
    /// <summary>
    /// 场景名称
    /// </summary>
    private string senceName;



    public SceneAssetBundle(string senceName)
    {
        this.senceName = senceName;
        this.relationList = new Dictionary<string, AssetBundleRelation>();
        this.nameCacheDic = new Dictionary<string, AssetCaching>();
    }
    /// <summary>
    /// 判断是否加载当前包
    /// </summary>
    /// <param name="bundleName"></param>
    /// <returns></returns>
    public bool isLoad(string bundleName) { return this.relationList.ContainsKey(bundleName); }
    /// <summary>
    /// 判断当前包是否加载完成
    /// </summary>
    /// <param name="bundleName"></param>
    /// <returns></returns>
    public bool isFinish(string bundleName) {
        if (this.isLoad(bundleName))
        {
            return this.relationList[bundleName].finished;
        }
        return false;
    }
    /// <summary>
    /// 加载资源包
    /// </summary>
    /// <param name="bundleName"></param>
    /// <param name="onProgress"></param>
    /// <param name="complete"></param>
    public void LoadAssetbundle(string bundleName, AssetBundleLoadProgress onProgress, LoadAssetBundleCallBack complete, params object[] param)
    {
        if (relationList.ContainsKey(bundleName))
        {
            Debug.LogWarning("此包已经加载 >> "+bundleName);
            return;
        }
        AssetBundleRelation assetBundleRelation=new AssetBundleRelation(bundleName, onProgress);
        relationList.Add(bundleName, assetBundleRelation);
        //开始加载
        complete(senceName, bundleName);
    }
    public IEnumerator Load(string bundleName, AssetBundleComplete onLoadComplete=null)
    {
        while (!ManifestLoader.Instance.finihed) yield return 0;

        AssetBundleRelation assetBundleRelation = relationList[bundleName];
        //获取这个包的所有依赖关系
        string[] dependencies = ManifestLoader.Instance.GetAllDependencies(bundleName);
        for (int i = 0; i < dependencies.Length; i++)
        {
            string dependenceName=dependencies[i];
            assetBundleRelation.AddDependencies(dependenceName);
            //加载所有依赖关系
            yield return LoadDependence(dependenceName, bundleName, assetBundleRelation.onProgress);
        }
        assetBundleRelation.onComplete = onLoadComplete;
        //真正开始加载这个包
        yield return assetBundleRelation.Load();
    }
    /// <summary>
    /// 加载依赖包
    /// </summary>
    /// <param name="bundleName"></param>
    /// <param name="referenceBundleName"></param>
    /// <param name="onProgress"></param>
    /// <returns></returns>
    private IEnumerator LoadDependence(string bundleName,string referenceBundleName, AssetBundleLoadProgress onProgress)
    {
        if (relationList.ContainsKey(bundleName))
        {
            AssetBundleRelation assetBundleRelation = relationList[bundleName];
            assetBundleRelation.AddReferencies(referenceBundleName);//添加被依赖关系
        }
        else
        {
            AssetBundleRelation assetBundleRelation = new AssetBundleRelation(bundleName, onProgress);
            assetBundleRelation.AddReferencies(referenceBundleName);//添加被依赖关系
            relationList.Add(bundleName, assetBundleRelation);
            //开始加载这个包的依赖关系
            yield return Load(bundleName);
        }

    }
    public AssetBundle Asset(string bundleName)
    {
        if (!relationList.ContainsKey(bundleName))
        {
            Debug.LogError("当前没有加载 >> " + bundleName);
            return null;
        }
        return relationList[bundleName].Asset;
    }
    public UnityEngine.Object LoadAsset(string bundleName,string assetName)
    {
        if (this.nameCacheDic.ContainsKey(bundleName))
        {
            UnityEngine.Object[] assets = this.nameCacheDic[bundleName].GetAssets(assetName);
            if(assets!=null && assets.Length > 0)return assets[0];
        }
        if (!relationList.ContainsKey(bundleName))
        {
            Debug.LogError("当前没有加载 >> "+bundleName);
            return null;
        }
        UnityEngine.Object asset = relationList[bundleName]?.LoadAsset(assetName);
       
        AssetCaching assetCaching = null;
        if (this.nameCacheDic.ContainsKey(bundleName))
            assetCaching = this.nameCacheDic[bundleName];
        else
        {
            assetCaching = new AssetCaching();
            this.nameCacheDic.Add(assetName, assetCaching);
        }
        assetCaching.AddAsset(assetName, new TempObject(asset));
        return asset;
    }
    public T LoadAsset<T>(string bundleName,string assetName) where T : UnityEngine.Object
    {
        if (typeof(T) == typeof(AssetBundle)) return relationList[bundleName].Asset as T;
        return this.LoadAsset(bundleName,assetName) as T;
    }

    public T[] LoadAssetAll<T>(string bundleName) where T : UnityEngine.Object
    {
        if (!relationList.ContainsKey(bundleName))
        {
            Debug.LogError("当前没有加载 >> " + bundleName);
            return null;
        }
        return relationList[bundleName]?.LoadAssetAll<T>();
    }
    /// <summary>
    /// 获取图集资源的全部子集
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="assetName"></param>
    /// <returns></returns>
    public UnityEngine.Object[] LoadAssetWithSubAssets(string bundleName, string assetName)
    {
        if (this.nameCacheDic.ContainsKey(bundleName))
        {
            UnityEngine.Object[] assets = this.nameCacheDic[bundleName].GetAssets(assetName);
            if (assets != null && assets.Length > 0) return assets;
        }
        if (!relationList.ContainsKey(bundleName))
        {
            Debug.LogError("当前没有加载 >> " + bundleName);
            return null;
        }
        UnityEngine.Object[] assetsList= relationList[bundleName]?.LoadAssetWithSubAssets(assetName);
        AssetCaching assetCaching = null;
        if (this.nameCacheDic.ContainsKey(bundleName))
            assetCaching = this.nameCacheDic[bundleName];
        else
        {
            assetCaching = new AssetCaching();
            this.nameCacheDic.Add(assetName, assetCaching);
        }
        assetCaching.AddAsset(assetName, new TempObject(assetsList));
        return assetsList;
    }
    /// <summary>
    /// 卸载资源
    /// </summary>
    /// <param name="asset"></param>
    public void UnLoadAsset(string bundleName,string assetname)
    {
        if (!nameCacheDic.ContainsKey(bundleName))
        {
            Debug.LogError("当前没有加载 >> " + bundleName+"无法卸载资源");
            return;
        }
        nameCacheDic[bundleName].UnLoadAsset(assetname);
        Resources.UnloadUnusedAssets();//卸载没有使用的资源
    }
    /// <summary>
    /// 卸载一个包的所有资源
    /// </summary>
    /// <param name="bundleName"></param>
    public void UnLoadAllAsset(string bundleName)
    {
        if (!nameCacheDic.ContainsKey(bundleName))
        {
            Debug.LogError("当前没有加载 >> " + bundleName + "无法卸载资源");
            return;
        }
        nameCacheDic[bundleName].UnLoadAllAsset();
        nameCacheDic.Remove(bundleName);
        Resources.UnloadUnusedAssets();//卸载没有使用的资源
    }
    /// <summary>
    /// 卸载所有资源
    /// </summary>
    public void UnLoadAll()
    {
        foreach (var item in nameCacheDic)
        {
            UnLoadAllAsset(item.Key);
        }
        nameCacheDic.Clear();
    }
    /// <summary>
    /// 卸载全部包和对应的资源
    /// </summary>
    public void DisposeAllAndUnLoadAll()
    {
        UnLoadAll();
        DisposeAll();
    }
    /// <summary>
    /// 释放assetbundle资源
    /// </summary>
    public void Dispose(string bundleName)
    {
        if (!relationList.ContainsKey(bundleName))
        {
            Debug.LogError("当前没有加载 >> " + bundleName);
            return;
        }
        //卸载依赖
        AssetBundleRelation assetBundleRelation = relationList[bundleName];
        if(assetBundleRelation != null)
        {
            string[] allDependences= assetBundleRelation.GetAllDependencies();
            foreach(string dependenceName in allDependences)
            {
                AssetBundleRelation bundleRelation = relationList[dependenceName];
                if (assetBundleRelation.RemoveReferencies(dependenceName))
                {
                    //递归卸载依赖
                    Dispose(bundleRelation.bundleNmae);
                }
            }
        }
        //卸载包
        if(assetBundleRelation.GetAllReferencies().Length <= 0)
        {
            relationList[bundleName]?.Dispose();
            relationList[bundleName] = null;
            nameCacheDic.Remove(bundleName);
        }
    }
    /// <summary>
    /// 卸载全部资源包
    /// </summary>
    public void DisposeAll()
    {
        foreach(var item in relationList)
        {
            Dispose(item.Key);
        }
        relationList.Clear();
    }
    /// <summary>
    /// 测试专用，获取当前assetbundle资源包的已经加载好的全部资源名称
    /// </summary>
    /// <returns></returns>
    public string[] GetAllAssetNames(string bundleName)
    {
        if (!relationList.ContainsKey(bundleName))
        {
            Debug.LogError("当前没有加载 >> " + bundleName);
            return null;
        }
        return relationList[bundleName]?.GetAllAssetNames();
    }
    public void Trace(string bundleName)
    {
        if (!relationList.ContainsKey(bundleName))
        {
            Debug.LogError("当前没有加载 >> " + bundleName);
            return;
        }
        relationList[bundleName]?.Trace();
    }
}
